﻿namespace LxCore
{
    public struct ConvectionDiscretization
    {
        public double phiC;
        public double phiD;
        public double phiD_phiU;
        public double gCf;
        public ConvectionDiscretization(double phiC, double phiD, double phiD_phiU, double gCf)
        {
            this.phiC = phiC;
            this.phiD = phiD;
            this.phiD_phiU = phiD_phiU;
            this.gCf = gCf;
        }
        public (double fC, double fD, double fConst) CalFactor_FOU()
        {
            return (1, 0, 0);//FOU
        }
        public (double fC, double fD, double fConst) CalFactor_SOU()
        {
            double phiU = phiD - phiD_phiU;
            return (1 + gCf, 0, -gCf * phiU);//SOU
        }
        public (double fC, double fD, double fConst) CalFactor_CD_DC()
        {
            double phiD_phiC = phiD - phiC;
            return (1, 0, gCf * phiD_phiC);//CD DC
        }
        public (double fC, double fD, double fConst) CalFactor_SOU_DC()
        {
            double phiC_phiU = phiC - phiD + phiD_phiU;
            return (1, 0, gCf * phiC_phiU);//SOU DC
        }
        public (double fC, double fD, double fConst) CalFactor_DownWind()
        {
            double phiD_phiC = phiD - phiC;
            return (1, 0, phiD_phiC);//DownWind
        }
        public (double fC, double fD, double fConst) CalFactor_SOU_CD_DC()
        {
            double phiD_phiC = phiD - phiC;
            double phiC_phiU = phiD_phiU - phiD_phiC;
            if (double.IsNegative(phiD_phiC))
            {
                if (!double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (phiC_phiU > phiD_phiC)
                {
                    return (1, 0, gCf * phiC_phiU);//SOU DC
                }
                else
                {
                    return (1, 0, gCf * phiD_phiC);//CD DC
                }
            }
            else
            {
                if (double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (phiC_phiU < phiD_phiC)
                {
                    return (1, 0, gCf * phiC_phiU);//SOU DC
                }
                else
                {
                    return (1, 0, gCf * phiD_phiC);//CD DC
                }
            }
        }
        public (double fC, double fD, double fConst) CalFactor_OSHER_DC()
        {
            double phiD_phiC = phiD - phiC;
            double phiC_phiU = phiD_phiU - phiD_phiC;
            if (double.IsNegative(phiD_phiC))
            {
                if (!double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (gCf * phiC_phiU > phiD_phiC)
                {
                    return (1, 0, gCf * phiC_phiU);//SOU DC
                }
                else
                {
                    return (1, 0, phiD_phiC);//DownWind
                }
            }
            else
            {
                if (double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (gCf * phiC_phiU < phiD_phiC)
                {
                    return (1, 0, gCf * phiC_phiU);//SOU DC
                }
                else
                {
                    return (1, 0, phiD_phiC);//DownWind
                }
            }
        }
        public (double fC, double fD, double fConst) CalFactor_MUSCL_DC()
        {
            double phiD_phiC = phiD - phiC;
            double phiC_phiU = phiD_phiU - phiD_phiC;
            if (double.IsNegative(phiD_phiC))
            {
                if (3 * phiC_phiU > phiD_phiC)
                {
                    if (!double.IsNegative(phiC_phiU))
                    {
                        return (1, 0, 0);
                    }
                    else
                    {
                        return (1, 0, 2 * gCf * phiC_phiU);//二阶迎风的两倍
                    }
                }
                else
                {
                    if (phiC_phiU * gCf > phiD_phiC * (2 - gCf))
                    {
                        return (1, 0, 0.5 * gCf * phiD_phiU);
                    }
                    else
                    {
                        return (1, 0, phiD_phiC);//DownWind
                    }
                }
            }
            else
            {
                if (3 * phiC_phiU < phiD_phiC)
                {
                    if (double.IsNegative(phiC_phiU))
                    {
                        return (1, 0, 0);
                    }
                    else
                    {
                        return (1, 0, 2 * gCf * phiC_phiU);//二阶迎风的两倍
                    }
                }
                else
                {
                    if (phiC_phiU * gCf < phiD_phiC * (2 - gCf))
                    {
                        return (1, 0, 0.5 * gCf * phiD_phiU);
                    }
                    else
                    {
                        return (1, 0, phiD_phiC);//DownWind
                    }
                }
            }
        }
        //非DC格式的在SIMPLE算法中可能存在波动不收敛问题
        public (double fC, double fD, double fConst) CalFactor_OSHER()
        {
            double phiD_phiC = phiD - phiC;
            double phiC_phiU = phiD_phiU - phiD_phiC;
            if (double.IsNegative(phiD_phiC))
            {
                if (!double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (gCf * phiC_phiU > phiD_phiC)
                {
                    double phiU = phiD - phiD_phiU;
                    return (1 + gCf, 0, -gCf * phiU);//SOU
                }
                else
                {
                    return (1, 0, phiD_phiC);//DownWind
                }
            }
            else
            {
                if (double.IsNegative(phiC_phiU))
                {
                    return (1, 0, 0);
                }
                else if (gCf * phiC_phiU < phiD_phiC)
                {
                    double phiU = phiD - phiD_phiU;
                    return (1 + gCf, 0, -gCf * phiU);//SOU
                }
                else
                {
                    return (1, 0, phiD_phiC);//DownWind
                }
            }
        }
        public (double fC, double fD, double fConst) CalFactor_MUSCL()
        {
            double phiD_phiC = phiD - phiC;
            double phiC_phiU = phiD_phiU - phiD_phiC;
            if (double.IsNegative(phiD_phiC))
            {
                if (3 * phiC_phiU > phiD_phiC)
                {
                    if (!double.IsNegative(phiC_phiU))
                    {
                        return (1, 0, 0);
                    }
                    else
                    {
                        gCf *= 2;
                        double phiU = phiD - phiD_phiU;
                        return (1 + gCf, 0, -gCf * phiU); ;//二阶迎风的两倍         
                    }
                }
                else
                {
                    if (phiC_phiU * gCf > phiD_phiC * (2 - gCf))
                    {
                        gCf *= 0.5;
                        double phiU = phiD - phiD_phiU;
                        return (1, gCf, -gCf *phiU);
                    }
                    else
                    {
                        return (1, 0, phiD_phiC);//DownWind
                    }
                }
            }
            else
            {
                if (3 * phiC_phiU < phiD_phiC)
                {
                    if (double.IsNegative(phiC_phiU))
                    {
                        return (1, 0, 0);
                    }
                    else
                    {
                        gCf *= 2;
                        double phiU = phiD - phiD_phiU;
                        return (1 + gCf, 0, -gCf * phiU); ;//二阶迎风的两倍        
                    }
                }
                else
                {
                    if (phiC_phiU * gCf < phiD_phiC * (2 - gCf))
                    {
                        gCf *= 0.5;
                        double phiU = phiD - phiD_phiU;
                        return (1, gCf, -gCf * phiU);
                    }
                    else
                    {
                        return (1, 0, phiD_phiC);//DownWind
                    }
                }
            }
        }
    }
}
